/**
 * File: AbstractNodeCutoffFilter.java
 * Created by: mhaimel
 * Created on: Mar 30, 2010
 * CVS:  $Id: AbstractNodeCutoffFilter.java 1.0 Mar 30, 2010 8:53:44 AM mhaimel Exp $
 */
package uk.ac.ebi.curtain.model.graph.curtain.filter;

import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicIntegerArray;

import uk.ac.ebi.curtain.model.graph.Node;
import uk.ac.ebi.curtain.model.graph.GraphAccess.TouchEach;
import uk.ac.ebi.curtain.model.graph.curtain.ContigInfo;
import uk.ac.ebi.curtain.model.graph.curtain.ReadWrapper;

/**
 * @author mhaimel
 *
 */
public abstract class AbstractNodeCutoffFilter implements TouchEach<Node<ContigInfo, ReadWrapper>> {
	
	private final AtomicIntegerArray cutoff;
	private final boolean maxEdge;
	private final ConcurrentLinkedQueue<Long> lenSet = new ConcurrentLinkedQueue<Long>(); 
	
	public AbstractNodeCutoffFilter(int[] cutoffCategory, boolean isMaxCutoff) {
		this.cutoff = new AtomicIntegerArray(cutoffCategory);
		this.maxEdge = isMaxCutoff;
	}
	
	@Override
	public void touch(Node<ContigInfo, ReadWrapper> node) {
		if(!node.isActive()){
			return;
		}
		int categories = getCategories();
		for(int cat = 0; cat < categories; ++cat){
			if(isOutOfRange(cat,node,getCutoff(cat),isMaxCutoff())){
//				if(node.getValue().getLength() > 350){
////				if(cat == 1){
//					System.out.print(cat +  ": " + node.getValue().getLength() + "\t"+node.getValue().getPartial(cat));
//					System.out.println();
//				}
				lenSet.add(node.getValue().getLength());
				invalidateNode(node);
				break;
			}
		}
	}

	protected boolean isMaxCutoff() {
		return maxEdge;
	}

	protected int getCutoff(int cat) {
		return this.cutoff.get(cat);
	}
	protected int getCategories() {
		return cutoff.length();
	}
	
	public Collection<Long> getLenSet() {
		return lenSet;
	}


	protected abstract boolean isOutOfRange(int cat, Node<ContigInfo, ReadWrapper> node, int cutoff, boolean isMaxCutoff);

	protected void invalidateNode(Node<ContigInfo, ReadWrapper> node){
		node.getActive().set(false);
	}

	
}
